package com.chunfeng.lerunapplication.utils;

import android.util.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.chunfeng.lerunapplication.entity.JsonRequest;
import okhttp3.*;

import java.io.File;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

/**
 * HTTP请求类
 *
 * @author by 春风能解释
 * <p>
 * 2023/11/22
 */
public class HttpUtils<T> {
    /**
     * 基本路径
     */
    private static final String baseUrl = "http://192.168.36.39:8080/";
    /**
     * 最大响应时间(秒)
     */
    private static final Long READ_TIME_OUT = 5L;

    /**
     * 发起HTTP请求并返回文件流
     *
     * @param request 请求体
     * @return 字节
     */
    private static byte[] executeHttpStream(Request.Builder request) {
        //创建线程
        Callable<byte[]> callable = new Callable<byte[]>() {
            /**
             * 执行方法
             *
             * @return 结果集
             */
            @Override
            public byte[] call() {
                Response response;
                try {
                    OkHttpClient.Builder builder = new OkHttpClient.Builder();
                    //发起HTTP请求
                    response = builder
                            .connectTimeout(READ_TIME_OUT, TimeUnit.SECONDS)
                            .build()
                            .newCall(request.build())
                            .execute();
                    ResponseBody body = response.body();
                    if (body == null) {
                        return null;
                    }
                    return body.bytes();
                } catch (Exception e) {
                    Log.w("exception", e.getLocalizedMessage());
                    return null;
                }
            }
        };
        //接收线程结果
        FutureTask<byte[]> future = new FutureTask<>(callable);
        //启动线程
        new Thread(future).start();
        try {
            return future.get();
        } catch (Exception e) {
            Log.w("exception", e.getLocalizedMessage());
            return null;
        }
    }

    /**
     * 发起HTTP请求
     *
     * @param request 请求对象
     * @param <T>     接收的类型
     */
    private static <T> JsonRequest<T> executeHttp(Request.Builder request) {
        //创建线程
        Callable<JsonRequest<T>> callable = new Callable<JsonRequest<T>>() {
            /**
             * 执行方法
             *
             * @return 结果集
             */
            @Override
            public JsonRequest<T> call() {
                JsonRequest<T> tJsonRequest = new JsonRequest<>();
                Response response;
                try {
                    OkHttpClient.Builder builder = new OkHttpClient.Builder();
                    //发起HTTP请求
                    response = builder
                            .connectTimeout(READ_TIME_OUT, TimeUnit.SECONDS)
                            .build()
                            .newCall(request.build())
                            .execute();
                    ResponseBody body = response.body();
                    if (body == null) {
                        return null;
                    }
                    String json = body.string();
                    tJsonRequest = JSON.parseObject(json, new TypeReference<JsonRequest<T>>() {
                    });
                    if (!tJsonRequest.getSuccess()) {
                        Log.w("HTTPException", tJsonRequest.getMessage());
                    }
                    return tJsonRequest;
                } catch (Exception e) {
                    Log.w("exception", e.getLocalizedMessage());
                    tJsonRequest.setMessage(e.getLocalizedMessage());
                    tJsonRequest.setStatus(500);
                    tJsonRequest.setSuccess(false);
                    return tJsonRequest;
                }
            }
        };
        //接收线程结果
        FutureTask<JsonRequest<T>> future = new FutureTask<>(callable);
        //启动线程
        new Thread(future).start();
        try {
            return future.get();
        } catch (Exception e) {
            Log.w("exception", e.getLocalizedMessage());
            return null;
        }
    }

    /**
     * 请求方法处理
     *
     * @param method     请求方法
     * @param body       请求体
     * @param newBuilder 请求对象
     */
    private static void createMethods(String method, Object body, Request.Builder newBuilder, Map<String, String> header) {
        String value = header == null ? null : header.get("Content-Type");
        //GET方法的特殊处理
        if (!method.equals("GET")) {
            if (body instanceof File) {
                newBuilder
                        .method(method, new MultipartBody
                                .Builder()
                                .setType(MultipartBody.FORM)
                                .addFormDataPart("file", ((File) body).getName(), RequestBody.create(MediaType.parse(value == null ? "image/jpeg" : value), (File) body))
                                .build());
            } else {
                newBuilder.method(method, //请求方法
                        RequestBody.create(
                                MediaType.parse(value == null ?
                                        "application/json"
                                        : value),//请求头
                                body != null ? JSON.toJSONString(body) : "")//请求体
                );//请求体
            }
        } else {
            newBuilder.get();
        }
    }

    /**
     * 请求头处理
     *
     * @param headers    请求头
     * @param newBuilder request对象
     */
    private static void createHeaders(Map<String, String> headers, Request.Builder newBuilder) {
        //请求头
        if (headers != null && !headers.isEmpty()) {
            for (Map.Entry<String, String> header : headers.entrySet()) {
                newBuilder.addHeader(header.getKey(), header.getValue());
            }
        }
    }

    /**
     * 路径参数处理
     *
     * @param params     参数
     * @param finallyUrl 最终处理路径
     */
    private static void createUrl(Map<String, Object> params, StringBuilder finallyUrl) {
        if (params != null && !params.isEmpty()) {
            //遍历
            for (Map.Entry<String, Object> param : params.entrySet()) {
                finallyUrl.append(param.getKey()).append("=").append(param.getValue()).append("&");
            }
            //截取最后
            if (finallyUrl.toString().endsWith("&")) {
                finallyUrl.substring(0, finallyUrl.length());
            }
        }
    }

    /**
     * 发起HTTP请求
     *
     * @param url     请求路径
     * @param method  请求方法
     * @param body    请求体
     * @param headers 请求头
     * @param params  请求参数
     * @return 结果集
     */
    public JsonRequest<T> sendHttpRequest(String url, String method, Object body, Map<String, String> headers, Map<String, Object> params) {
        Request.Builder request = initRequest(url, method, body, headers, params);
        //执行请求方法
        return executeHttp(request.build().newBuilder());
    }

    /**
     * 获取图片流
     *
     * @param url     请求路径
     * @param method  请求方法
     * @param body    请求体
     * @param headers 请求头
     * @param params  请求参数
     * @return 图片字节流
     */
    public byte[] getImage(String url, String method, Object body, Map<String, String> headers, Map<String, Object> params) {
        //初始化
        Request.Builder request = initRequest(url, method, body, headers, params);
        //执行请求方法
        return executeHttpStream(request.build().newBuilder());
    }

    /**
     * 初始化请求体
     *
     * @param url     请求路径
     * @param method  请求方法
     * @param body    请求体
     * @param headers 请求头
     * @param params  请求参数
     * @return 请求体-
     */
    private Request.Builder initRequest(String url, String method, Object body, Map<String, String> headers, Map<String, Object> params) {
        //创建请求对象
        Request.Builder request = new Request.Builder();
        StringBuilder finallyUrl = new StringBuilder();
        finallyUrl.append(baseUrl)
                .append(url)
                .append("?");
        //路径参数处理
        createUrl(params, finallyUrl);
        //请求头
        createHeaders(headers, request);
        //拼接路径
        request.url(finallyUrl.toString());
        //请求方法处理
        createMethods(method, body, request, headers);
        return request;
    }
}
